@use '@material/typography' as mdc-typography;
@use 'sass:map';
@use '../mdc-theming/all-theme';
@use '../../material/core/theming/theming';
@use '../../material/core/typography/typography';
@use '../mdc-helpers/mdc-helpers';

/// Generates an Angular Material typography config based on values from the official Material
/// Design spec implementation (MDC Web). All arguments are optional, but may be passed to override
/// the default values. The `mat-typography-level` function can be used to generate a custom
/// typography level map which can be passed to this function to override one of the default levels.
///
/// @param {String} $font-family The font family to use for levels where it is not explicitly
///     specified.
/// @param {Map} $headline-1 The font settings for the headline-1 font level.
/// @param {Map} $headline-2 The font settings for the headline-2 font level.
/// @param {Map} $headline-3 The font settings for the headline-3 font level.
/// @param {Map} $headline-4 The font settings for the headline-4 font level.
/// @param {Map} $headline-5 The font settings for the headline-5 font level.
/// @param {Map} $headline-6 The font settings for the headline-6 font level.
/// @param {Map} $subtitle-1 The font settings for the subtitle-1 font level.
/// @param {Map} $subtitle-2 The font settings for the subtitle-2 font level.
/// @param {Map} $body-1 The font settings for the body-1 font level.
/// @param {Map} $body-2 The font settings for the body-2 font level.
/// @param {Map} $caption The font settings for the caption font level.
/// @param {Map} $button The font settings for the button font level.
/// @param {Map} $overline The font settings for the overline font level.
/// @return {Map} A map containing font settings for each of the levels in the Material Design spec.
@function define-typography-config(
  $font-family: mdc-typography.$font-family,
  $headline-1:  mdc-helpers.mat-typography-config-level-from-mdc(headline1),
  $headline-2:  mdc-helpers.mat-typography-config-level-from-mdc(headline2),
  $headline-3:  mdc-helpers.mat-typography-config-level-from-mdc(headline3),
  $headline-4:  mdc-helpers.mat-typography-config-level-from-mdc(headline4),
  $headline-5:  mdc-helpers.mat-typography-config-level-from-mdc(headline5),
  $headline-6:  mdc-helpers.mat-typography-config-level-from-mdc(headline6),
  $subtitle-1:  mdc-helpers.mat-typography-config-level-from-mdc(subtitle1),
  $subtitle-2:  mdc-helpers.mat-typography-config-level-from-mdc(subtitle2),
  $body-1:      mdc-helpers.mat-typography-config-level-from-mdc(body1),
  $body-2:      mdc-helpers.mat-typography-config-level-from-mdc(body2),
  $caption:     mdc-helpers.mat-typography-config-level-from-mdc(caption),
  $button:      mdc-helpers.mat-typography-config-level-from-mdc(button),
  $overline:    mdc-helpers.mat-typography-config-level-from-mdc(overline),
) {
  // Declare an initial map with all of the levels.
  $config: (
      headline-1: $headline-1,
      headline-2: $headline-2,
      headline-3: $headline-3,
      headline-4: $headline-4,
      headline-5: $headline-5,
      headline-6: $headline-6,
      subtitle-1: $subtitle-1,
      subtitle-2: $subtitle-2,
      body-1:     $body-1,
      body-2:     $body-2,
      caption:    $caption,
      button:     $button,
      overline:   $overline,
  );

  // Loop through the levels and set the `font-family` of the ones that don't have one to the base.
  // Note that Sass can't modify maps in place, which means that we need to merge and re-assign.
  @each $key, $level in $config {
    @if map.get($level, font-family) == null {
      $new-level: map.merge($level, (font-family: $font-family));
      $config: map.merge($config, ($key: $new-level));
    }
  }

  // Add the base font family to the config.
  @return map.merge($config, (font-family: $font-family));
}

@mixin all-mdc-component-typographies($config-or-theme: null) {
  $config: if(theming.private-is-theme-object($config-or-theme),
      theming.get-typography-config($config-or-theme), $config-or-theme);

  // If no actual color configuration has been specified, create a default one.
  @if $config == null {
    $config: typography.define-typography-config();
  }

  @include all-theme.all-mdc-component-themes((
    color: null,
    density: null,
    typography: $config,
  ));
}

// @deprecated Use `all-mdc-component-typographies`.
@mixin angular-material-mdc-typography($config-or-theme: null) {
  @include all-mdc-component-typographies($config-or-theme);
}
